import React from 'react';
import {Button, Card, Flex, Input, InputRef, Select, Space, Tag} from "antd";
import {CompatClient, Stomp} from '@stomp/stompjs';
import LogFactory from "log/LogFactory";
import {LoginConstant} from "constant/LoginConstant";
import ButtonGroup from "antd/es/button/button-group";

const log = LogFactory.getLog("WebSocketComponent");
const WebSocketComponent = () => {

    const loginUser = localStorage.getItem(LoginConstant.USERNAME) as string;

    const subscribed = React.useRef<string[]>([]);

    const client = React.useRef<CompatClient>();
    const [connected, setConnected] = React.useState(false);

    const [onlineUser, setOnlineUser] = React.useState<object[]>([]);

    const inputRef = React.useRef<InputRef>(null);
    const selectRef = React.useRef<any>("all");

    /**
     * 连接WebSocket
     */
    const connectSocket = () => {
        if (connected){
            log.debug("WebSocket已连接");
            return ;
        }
        log.debug("连接WebSocket ===> 用户 = ", localStorage.getItem(LoginConstant.USERNAME));
        const cli:CompatClient = Stomp.client('ws://localhost:8888/socket',["token-protocol." + localStorage.getItem(LoginConstant.USERNAME), "v12.stomp"]) ;
        cli.heartbeat={incoming: 10000, outgoing: 10000};
        cli.debug = (msg) => {
            // log.debug(msg);
        };
        cli.connect({Authorization: "admin"}, () =>socketConnectedHandler(cli));
        cli.onWebSocketError = function (evt) {
            log.warn('socket连接失败: ', evt);
        } ;
    };

    /**
     * WebSocket连接成功处理
     */
    const socketConnectedHandler = (cli: CompatClient) => {
        log.debug("socket连接成功,处理监听");
        client.current = cli;
        cli.onWebSocketClose = function (evt) {
            log.debug("socket连接已断开", evt);
            setConnected(false) ;
            subscribed.current = [] ;
        } ;
        setTimeout(() => {
            cli.subscribe("/topic/onlineUser",msg => {
                const ou = JSON.parse(msg.body) ;
                log.debug("收到订阅消息[onlineUser(在线用户)]: ", ou);
               let temp = Object.keys(ou).map(k => {
                    // log.debug("用户: ", k, " 上线了");
                    return {userName: k,key: ou[k]} ;
                }) ;
               setOnlineUser(temp) ;

            });
        },800) ;
        setConnected(true);
    };

    /**
     * 订阅一对一消息
     */
    const subscribeOneToOne = () => {
        if (subscribed.current.includes("/user-single/" + loginUser + "/user/private")){
            log.debug("已订阅消息[private(一对一消息)]");
            return ;
        }
        if (connected && client.current){
            let res = client.current.subscribe("/user-single/" + loginUser + "/user/private",(msg) => {
                log.debug('接收一对一消息消息:',JSON.parse(msg.body));
            }) ;

            log.debug("订阅消息[private(一对一消息)],订阅结果 = ", res);
        }
    } ;

    /**
     * 订阅系统消息
     */
    const subscribeSystemMessage = () => {
        if (subscribed.current.includes("/topic/public")){
            log.debug("已订阅消息[public(系统消息)]");
            return ;
        }
       if (connected && client.current){
          let res = client.current.subscribe("/topic/public",msg => {
               subscribed.current.push("/topic/public");
               log.debug("收到订阅消息[public(系统消息)]: ", JSON.parse(msg.body));
           });
          log.debug("订阅消息[public(系统消息)],订阅结果 = ", res);

       }
    } ;

    const sendSystemMessage = () => {
        if (connected && client.current){
            client.current.send("/topic/public",{},JSON.stringify({
                info: "大家好,我是" + localStorage.getItem(LoginConstant.USERNAME) + "，我上线了",
                to: "all",
                from: localStorage.getItem(LoginConstant.USERNAME)
            }));
            log.debug("发送系统消息");
        }
    } ;

    const sendOnoToOneMessage = () => {

        log.debug("发送一对一消息",selectRef.current,inputRef.current?.input?.value);
        const msg = {
            info: inputRef.current?.input?.value ,
            to: selectRef.current ,
            from: loginUser ,
            type: "single"
        } ;
        client.current?.send("/sendOneToOne",{},JSON.stringify(msg));
    } ;

    /**
     * 关闭WebSocket连接
     */
    const closeSocket = () => {
        log.debug("关闭WebSocket连接 ===> 用户 = ", localStorage.getItem(LoginConstant.USERNAME));
        client.current?.disconnect();
    };

    return (
        <Card
            title="WebSocket"
            extra={"extra"}
            actions={[
                <Space>
                    Socket状态：
                    <Tag color={connected ? "#0b420b" : "#f40"}>{connected ? "已连接" : "未连接"}</Tag>
                </Space>,
                <ButtonGroup>
                    <Button disabled={false} type={"primary"} onClick={connectSocket}>当前用户</Button>
                    <Button disabled={false} type={"dashed"}
                            onClick={closeSocket}>{localStorage.getItem(LoginConstant.USERNAME)}</Button>
                </ButtonGroup>
            ]}
        >
            <h3>聊天</h3>
            <Flex justify={"space-between"} gap={10}>

                <Select onChange={ value => selectRef.current= value } defaultValue={"all"} style={{width: "300px"}}>
                    <Select.Option value="all">所有人</Select.Option>
                    {
                        onlineUser.map((ou: any) => {
                            return <Select.Option key={ou.key} value={ou.userName}>{ou.userName}</Select.Option>
                        })
                    }
                </Select>

                <Space.Compact style={{width: '100%'}}>
                    <Input ref={inputRef} defaultValue="Combine input and button"/>
                    <Button type="primary" onClick={sendOnoToOneMessage}>发送消息</Button>
                </Space.Compact>
            </Flex>
            <hr/>


            <Space>
                <Button disabled={false} type={"primary"} onClick={connectSocket}>打开Socket</Button>
                <Button disabled={false} type={"primary"} onClick={subscribeSystemMessage}>订阅系统消息</Button>
                <Button disabled={false} type={"primary"} onClick={subscribeOneToOne}>订阅一对一消息</Button>
                <Button disabled={false} type={"primary"} danger onClick={closeSocket}>断开Socket</Button>
            </Space>
            <hr/>
            <Space>
                <Button disabled={false} type={"primary"} onClick={sendSystemMessage}>发送系统消息</Button>
            </Space>

        </Card>
    );
};

export default WebSocketComponent;